package com.mdn.steelcase.dao.impl;

import static com.mdn.steelcase.dao.GenericOfyService.ofy;

import java.util.List;

import com.googlecode.objectify.cmd.Query;
import com.mdn.steelcase.dao.GenericDao;
import com.mdn.steelcase.exception.ReflectionException;
import com.mdn.steelcase.helper.ReflectionHelper;

public class GenericDaoImpl<T> implements GenericDao<T> {

	private Class<T> persistentClass;

	public GenericDaoImpl(final Class<T> persistentClass) {
		this.persistentClass = persistentClass;
	}

	@Override
	public T save(T instance) {
		ofy().save().entity(instance).now();
		return instance;
	}

	@Override
	public T update(T instance) {
		return save(instance);
	}

	@Override
	public void delete(Long id) {
		delete(get(id));
	}

	@Override
	public void delete(T instance) {
		ofy().delete().entity(instance).now();
	}

	@Override
	public T get(Long id) {
		return ofy().load().type(persistentClass).id(id).get();
	}

	@Override
	public List<T> getAll() {
		return ofy().load().type(persistentClass).list();
	}

	@Override
	public boolean exist(Long id) {
		return (get(id) != null);
	}

	@Override
	public List<T> findByColumn(String columnName, Object value) {
		return ofy().load().type(persistentClass).filter(columnName, value)
				.list();
	}

	@Override
	public T findSingleByColumn(String columnName, Object value) {
		return ofy().load().type(persistentClass).filter(columnName, value)
				.first().get();

	}

	public T findSingleByExample(T example, String... propertyNames)
			throws ReflectionException {
		Query<T> query = ofy().load().type(persistentClass);
		for (String property : propertyNames) {
			query = query.filter(property,
					ReflectionHelper.executeGetMethod(example, property));
		}

		return query.first().get();
	}

	public List<T> findByExample(T example, String... propertyNames)
			throws ReflectionException {
		Query<T> query = ofy().load().type(persistentClass);
		for (String property : propertyNames) {
			query = query.filter(property,
					ReflectionHelper.executeGetMethod(example, property));
		}
		return query.list();
	}
}
